package com.imu.utils;

import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

/***
 * 短UUID
 * @author sunhongwei
 * @email sunhongwei@gmail.com
 * @date 2017年11月4日 上午11:07:35
 */
public class ShortUUID
{
  static final char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };

  static final Map<Character, Integer> digitMap = new HashMap<Character, Integer>();

  private static final int MAX_RADIX = digits.length;
  
  static
  {
	  for (int i = 0; i < MAX_RADIX; i++)
	  {
		  digitMap.put(Character.valueOf(digits[i]), Integer.valueOf(i));
	  }
  }

  private static String toString(long i, int radix)
  {
    if ((radix < 2) || (radix > MAX_RADIX))
      radix = 10;
    if (radix == 10) {
      return Long.toString(i);
    }
    int charPos = 64;

    char[] buf = new char[65];
    boolean negative = i < 0L;

    if (!negative) {
      i = -i;
    }

    while (i <= -radix) {
      buf[(charPos--)] = digits[((int)-(i % radix))];
      i /= radix;
    }
    buf[charPos] = digits[((int)-i)];

    if (negative) {
      buf[(--charPos)] = '-';
    }

    return new String(buf, charPos, 65 - charPos);
  }

  private static NumberFormatException forInputString(String s) {
    return new NumberFormatException("For input string: \"" + s + "\"");
  }

  public static long toNumber(String s, int radix)
  {
    if (s == null) {
      throw new NumberFormatException("null");
    }

    if (radix < 2) {
      throw new NumberFormatException("radix " + radix + " less than Numbers.MIN_RADIX");
    }

    if (radix > MAX_RADIX) {
      throw new NumberFormatException("radix " + radix + " greater than Numbers.MAX_RADIX");
    }

    long result = 0L;
    boolean negative = false;
    int i = 0; int len = s.length();
    long limit = -9223372036854775807L;

    if (len > 0) {
      char firstChar = s.charAt(0);
      if (firstChar < '0') {
        if (firstChar == '-') {
          negative = true;
          limit = -9223372036854775808L;
        } else if (firstChar != '+') {
          throw forInputString(s);
        }
        if (len == 1) {
          throw forInputString(s);
        }
        i++;
      }
      long multmin = limit / radix;
      while (i < len) {
        Integer digit = (Integer)digitMap.get(Character.valueOf(s.charAt(i++)));
        if (digit == null) {
          throw forInputString(s);
        }
        if (digit.intValue() < 0) {
          throw forInputString(s);
        }
        if (result < multmin) {
          throw forInputString(s);
        }
        result *= radix;
        if (result < limit + digit.intValue()) {
          throw forInputString(s);
        }
        result -= digit.intValue();
      }
    } else {
      throw forInputString(s);
    }
    
    return negative ? result : -result;
  }

  private static String digits(long val, int digits)
  {
	  long hi = 1L << digits * 4;
	  return toString(hi | val & hi - 1L, MAX_RADIX).substring(1);
  }

  public static String generate()
  {
    UUID uuid = UUID.randomUUID();
    StringBuilder sb = new StringBuilder();

    sb.append(digits(uuid.getMostSignificantBits() >> 32, 8));
    sb.append(digits(uuid.getMostSignificantBits() >> 16, 4));
    sb.append(digits(uuid.getMostSignificantBits(), 4));
    sb.append(digits(uuid.getLeastSignificantBits() >> 48, 4));
    sb.append(digits(uuid.getLeastSignificantBits(), 12));
    return sb.toString();
  }

  public static String uuid() {
    UUID uuid = UUID.randomUUID();
    String id = Long.toString(uuid.getLeastSignificantBits(), 36);
    if (id.length() == 13) {
      if (id.startsWith("-")) return id.replace("-", "0");
      return id;
    }
    return id.substring(1);
  }
  
  public static BigInteger bigUUID()
  {
      UUID id = UUID.randomUUID();
      ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
      bb.putLong(id.getMostSignificantBits());
      bb.putLong(id.getLeastSignificantBits());
      return new BigInteger(1, bb.array());
  }

  public static String UUID()
  {
	  UUID uuid = UUID.randomUUID();
	  return uuid.toString().replace("-", "");
  }
  
  public static String shortUUID() 
  {
	    StringBuffer shortBuffer = new StringBuffer();
	    String uuid = UUID.randomUUID().toString().replace("-", "");
	    
	    for (int i = 0; i < 8; i++) 
	    {
	        String str = uuid.substring(i * 4, i * 4 + 4);
	        int x = Integer.parseInt(str, 16);
	        shortBuffer.append(digits[x % 0x3E]);
	    }
	    
	    return shortBuffer.toString();
	}
  
  public static void main(String[] args) 
  {
	  Set<String> set = new HashSet<String>();
	  
	  for (int i = 0; i < 1000000; i++) {
		  set.add(generate());
		  System.out.println(generate());
	  }
	  
	  System.out.println(set.size());
  }
}